package com.gmail.mariska.martin.jpa;

import javax.persistence.EntityManager;
import javax.persistence.EntityTransaction;
import javax.persistence.OptimisticLockException;
import javax.persistence.RollbackException;

import org.apache.log4j.Logger;

public class Pertask {
	static final Logger logger = Logger.getLogger(Pertask.class);

	EntityManager em = null;
	private static final ThreadLocal<Pertask> THREAD_LOCAL_INSTANCE = new ThreadLocal<Pertask>() {
		@Override
		protected Pertask initialValue() {
			return new Pertask();
		}
	};

	public Pertask() {
		em = Perzistence.getInstance().createEntityManager();
	}

	public EntityManager getEntityManager() {
		return em;
	}

	public/* synchronized */static Pertask getInstance() {
		return THREAD_LOCAL_INSTANCE.get();
	}

	public <T> T transactionForWrite(PertaskCommand<T> pcmd) {
		EntityTransaction t = em.getTransaction();
		t.begin();
		try {
			T pertaskCommandResult = pcmd.execute(this);
			t.commit();
			return pertaskCommandResult;
		} catch (RollbackException e) {
			if (t.isActive()) {
				t.rollback();
			}
			logger.warn(this + " is rollbacking. ERR:" + e.getMessage());
		} catch (OptimisticLockException e) {
			if (t.isActive()) {
				t.rollback();
			}
			logger.warn(this + " udaje zmenil jiny uzivatel. ERR:" + e.getMessage());
		}
		return null;
	}

	public <T> T transactionForReadOnly(PertaskCommand<T> pcmd) {
		EntityTransaction t = em.getTransaction();
		t.setRollbackOnly();
		t.begin();
		try {
			T pertaskCommandResult = pcmd.execute(this);
			t.rollback();
			return pertaskCommandResult;
		} catch (RollbackException e) {
			if (t.isActive()) {
				t.rollback();
			}
			logger.warn(this + " is rollbacking. ERR:" + e.getMessage());
		} catch (OptimisticLockException e) {
			if (t.isActive()) {
				t.rollback();
			}
			logger.warn(this + " udaje zmenil jiny uzivatel. ERR:" + e.getMessage());
		}
		return null;
	}

}
